package com.glsc.ngateway.platform.service.costallocation;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.glsc.ngateway.common.api.common.utils.PageUtil;
import com.glsc.ngateway.common.api.ldap.dto.LdapEhrEmpDto;
import com.glsc.ngateway.common.api.platform.dto.user.PlatformUserDto;
import com.glsc.ngateway.common.api.platform.resp.PlatformResponse;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.User;
import com.glsc.ngateway.common.base.exception.PlatformException;
import com.glsc.ngateway.platform.aspect.UserCache;
import com.glsc.ngateway.platform.domain.costallocation.*;
import com.glsc.ngateway.platform.dto.BusiSystemInfoQueryDto;
import com.glsc.ngateway.platform.repo.costallocation.HisBusiSystemInfoRepo;
import com.glsc.ngateway.platform.repo.costallocation.HisDepCostAllocationRepo;
import com.glsc.ngateway.platform.service.UserService;
import com.glsc.ngateway.platform.utils.SpecificationUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.glsc.ngateway.common.api.common.enums.Constant.COSTALLOCATION_BUSISYSTEMINFO_ADMIN;
import static com.glsc.ngateway.common.api.common.enums.Constant.COSTALLOCATION_HISBUSISYSTEMINFO_ADMIN;
import static com.glsc.ngateway.platform.service.costallocation.HisIpInfoService.compareFields;

/**
 * @author guoj
 * @description: 历史业务系统
 * @date 2024/7/19 9:46
 */
@Service
public class HisBusiSystemInfoService {
    @Autowired
    private UserCache userCache;
    @Autowired
    private HttpServletRequest request;
    @Resource
    private UserService userService;
    @Autowired
    private HisBusiSystemInfoRepo hisBusiSystemInfoRepo;
    @Autowired
    private HisDepCostAllocationService hisDepCostAllocationService;
    @Autowired
    private HisDepCostAllocationRepo hisDepCostAllocationRepo;
    private static Logger logger = LoggerFactory.getLogger(HisBusiSystemInfoService.class);
    public Page<HisBusiSystemInfo> findPage(BusiSystemInfoQueryDto busiSystemInfoQueryDto) {
        logger.info("开始查询历史系统信息：{}", busiSystemInfoQueryDto.toString());
        String pageSizeQuery = busiSystemInfoQueryDto.getPageSize();
        String pageNoQuery = busiSystemInfoQueryDto.getPageNo();
        Integer pageNo = Objects.nonNull(pageNoQuery) ? Integer.parseInt(pageNoQuery) : null;
        Integer pageSize = Objects.nonNull(pageSizeQuery) ? Integer.parseInt(pageSizeQuery) : null;
        pageNo = PageUtil.initPageNo(pageNo);
        pageSize = PageUtil.initPageSize(pageSize);
        Sort.Direction direction = Sort.Direction.DESC;
        String sort = "id";
        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, direction, sort);

        Map<String, Object> param = new HashMap<>();

        PlatformUserDto user = userCache.get(request);
        Set<String> roleNames = new HashSet<>(user.getRoles());
        //个人数据 否则全部数据
        if (!"itadmin".equals(user.getUsername())
                && !roleNames.contains("itadmin")
                && !roleNames.contains(COSTALLOCATION_HISBUSISYSTEMINFO_ADMIN)){
            param.put("LIKE_systemUserId",user.getUsername());
        }
        String createStart = busiSystemInfoQueryDto.getCreateStart();
        if(StringUtils.isNotBlank(createStart)){
            LocalDateTime temp = LocalDate.parse(createStart).atStartOfDay();
            LocalDateTime localDateTime = temp.minusDays(1);
            param.put("GTE_createTime",localDateTime);
        }
        String createEnd = busiSystemInfoQueryDto.getCreateEnd();
        if(StringUtils.isNotBlank(createEnd)){
            LocalDateTime temp = LocalDate.parse(createEnd).atStartOfDay();
            param.put("LTE_createTime",temp);
        }

        String systemClass = busiSystemInfoQueryDto.getSystemClass();
        if (StrUtil.isNotEmpty(systemClass)) {
            param.put("EQ_systemClass", systemClass);
        }
        String mainClass = busiSystemInfoQueryDto.getMainClass();
        if (StrUtil.isNotEmpty(mainClass)) {
            param.put("EQ_mainClass", mainClass);
        }
        String systemClassNo = busiSystemInfoQueryDto.getSystemClassNo();
        if (StrUtil.isNotEmpty(systemClassNo)) {
            param.put("EQ_systemClassNo", systemClassNo);
        }
        Map<String, Object> paramCostAllocation = new HashMap<>();
        String depGradeOneId = busiSystemInfoQueryDto.getDepGradeOneId();
        if (StrUtil.isNotEmpty(depGradeOneId)) {
            paramCostAllocation.put("EQ_depGradeOneId", depGradeOneId);
        }
        String depGradeTwoId = busiSystemInfoQueryDto.getDepGradeTwoId();
        if (StrUtil.isNotEmpty(depGradeTwoId)) {
            paramCostAllocation.put("EQ_depGradeTwoId", depGradeTwoId);
        }
        String depLeader = busiSystemInfoQueryDto.getDepLeader();
        if (StrUtil.isNotEmpty(depLeader)) {
            paramCostAllocation.put("EQ_depLeader", depLeader);
        }
        List<HisBusiSystemInfo> content = hisBusiSystemInfoRepo.findAll(SpecificationUtil.buildSpecification(param, HisBusiSystemInfo.class));
        if (!"itadmin".equals(user.getUsername())
                && !roleNames.contains("itadmin")
                && !roleNames.contains(COSTALLOCATION_HISBUSISYSTEMINFO_ADMIN)){
            //避免名字内部包含关系   haoj  shaojx
            content = content.stream().filter(x -> {
                String systemUserId = x.getSystemUserId();
                if(StrUtil.isBlank(systemUserId)){
                    return false;
                }
                List<String> strings = Arrays.asList(systemUserId.split(","));
                if (strings.size() > 1) {
                    if (strings.contains(user.getUsername())) {
                        return true;
                    } else {
                        return false;
                    }
                } else {
                    return true;
                }
            }).collect(Collectors.toList());
        }

        //查询责任人
        String systemUserIdQuery = busiSystemInfoQueryDto.getSystemUserId();
        if(StrUtil.isNotEmpty(systemUserIdQuery)){
            content = content.stream().filter(x -> {
                String systemUserId = x.getSystemUserId();
                if(StrUtil.isBlank(systemUserId)){
                    return false;
                }
                List<String> strings = Arrays.asList(systemUserId.split(","));
                return strings.contains(systemUserIdQuery);
            }).collect(Collectors.toList());
        }
        List<HisBusiSystemInfo> resultList = new ArrayList<>();
        if (content.size() != 0) {
            Map<String, String> oaAccount2Username = this.getUserAccount(content);
            Set<Long> collect = content.stream().map(HisBusiSystemInfo::getId).collect(Collectors.toSet());
            Map<Long, List<HisDepCostAllocation>> systemid2List = hisDepCostAllocationService.queryBySystemIdSet(collect,paramCostAllocation);
            for (HisBusiSystemInfo temp : content) {
                String systemUserId = temp.getSystemUserId();
                //拼接一个或多个全部责任人
                if(!StrUtil.isEmpty(systemUserId)){
                    if(systemUserId.contains(",")){
                        String[] split = systemUserId.split(",");
                        List<String> oaaccounts = Arrays.asList(split);
                        List<String> userNameList = new ArrayList<>();
                        for(String oaaccount : oaaccounts){
                            String userNameTemp = oaAccount2Username.get(oaaccount);
                            if(StrUtil.isEmpty(userNameTemp)){
                                continue;
                            }
                            userNameList.add(userNameTemp);
                        }
                        temp.setSystemUserName(StringUtils.join(userNameList, ","));
                    }else{
                        temp.setSystemUserName(oaAccount2Username.get(systemUserId));
                    }
                }
                List<HisDepCostAllocation> depCostAllocationList = systemid2List.get(temp.getId());
                if (depCostAllocationList != null) {
                    temp.setHisDepCostAllocationList(depCostAllocationList);
                    resultList.add(temp);
                }else{
                    if(paramCostAllocation.size() ==0){
                        temp.setHisDepCostAllocationList(new ArrayList<>());
                        resultList.add(temp);
                    }
                }
            }
        }
        List<HisBusiSystemInfo> orderedDesc = resultList.stream().sorted(new Comparator<HisBusiSystemInfo>() {
            @Override
            public int compare(HisBusiSystemInfo o1, HisBusiSystemInfo o2) {
                return o2.getId().compareTo(o1.getId());
            }
        }).collect(Collectors.toList());
        return PageUtil.listConvertToPage(orderedDesc,pageable);
    }

    /**
     * 生成oa账户到姓名
     * @param content
     * @return
     */
    private Map<String,String> getUserAccount(List<HisBusiSystemInfo> content){
        Set<String> systemUserIdSet = content.stream()
                .filter(x -> Objects.nonNull(x.getSystemUserId()))
                .map(HisBusiSystemInfo::getSystemUserId)
                .collect(Collectors.toSet());
        List<String> systemUserIdList = new ArrayList<>();
        for (String systemUserIdTemp : systemUserIdSet) {
            if(StrUtil.isEmpty(systemUserIdTemp)){
                continue;
            }
            //多个责任人
            if(systemUserIdTemp.contains(",")){
                String[] split = systemUserIdTemp.split(",");
                systemUserIdList.addAll( Arrays.asList(split));
            }else{
                systemUserIdList.add(systemUserIdTemp);
            }
        }

        List<User> userList = userService.findAllByAccountList(systemUserIdList);
        return userList
                .stream()
                .collect(Collectors.toMap(User::getUsername, User::getName));
    }

    public Map<String,Object> compareDifferentPoint(Long leftId, Long rightId) {
        if (leftId.compareTo(rightId) == 0) {
            throw PlatformException.error("请选择两笔不同流水");
        }
        //左对应变更前  右对应变更后
        //要求left < right
        if (leftId.compareTo(rightId) > 0) {
            Long temp = leftId;
            leftId = rightId;
            rightId = temp;
        }
        Set<Long> ids = new HashSet<>();
        ids.add(leftId);
        ids.add(rightId);
        List<HisBusiSystemInfo> hisBusiSystemInfos = hisBusiSystemInfoRepo.queryByids(ids);
        if (CollectionUtil.isEmpty(hisBusiSystemInfos) || hisBusiSystemInfos.size() != 2) {
            throw PlatformException.error("未找到相关流水");
        }
        List<HisDepCostAllocation> hisIpDetailInfos = hisDepCostAllocationRepo.queryByHisIds(ids);
        Map<Long, List<HisDepCostAllocation>> infoid2List = hisIpDetailInfos.stream()
                .collect(Collectors.groupingBy(HisDepCostAllocation::getSystemInfoId));
        Map<String, Object> result = new HashMap<>();
        HisBusiSystemInfo left = new HisBusiSystemInfo();
        HisBusiSystemInfo right = new HisBusiSystemInfo();
        Set<String> OperatorOA = hisBusiSystemInfos.stream().map(HisBusiSystemInfo::getOperator).collect(Collectors.toSet());
        List<LdapEhrEmpDto> usersFromEhr = userService.getUsersFromEhr(new ArrayList<>(OperatorOA));
        Map<String, String> oa2name = usersFromEhr.stream()
                .collect(Collectors.toMap(LdapEhrEmpDto::getBadge, LdapEhrEmpDto::getName));
        for (HisBusiSystemInfo temp : hisBusiSystemInfos) {
            Long id = temp.getId();
            List<HisDepCostAllocation> detailTemp = infoid2List.get(id);
            if (leftId.compareTo(id) == 0) {
                BeanUtils.copyProperties(temp,left);
                String systemUserId = left.getSystemUserId();
                String operator = left.getOperator();
                left.setSystemUserName(oaAccount2Name(systemUserId));
                left.setOperatorName(oa2name.get(operator));
                left.setHisDepCostAllocationList(detailTemp);
                result.put("left", left);
            }
            if (rightId.compareTo(id) == 0) {
                BeanUtils.copyProperties(temp,right);
                String systemUserId = right.getSystemUserId();
                String operator = right.getOperator();
                right.setSystemUserName(oaAccount2Name(systemUserId));
                right.setOperatorName(oa2name.get(operator));
                right.setHisDepCostAllocationList(detailTemp);
                result.put("right", right);
            }
        }
        String[] ignoreField = {"id","operator","systemClassNo","systemUserId","hisDepCostAllocationList"};
        Map<String, List<Object>> stringListMap = compareFields(right, left,ignoreField);
        result.put("diff", stringListMap.keySet());
        return result;
    }


    public String oaAccount2Name(String oaAccount){
        if(StrUtil.isBlank(oaAccount)){
            return null;
        }
        String[] split = oaAccount.split(",");
        List<String> strings = Arrays.asList(split);
        List<LdapEhrEmpDto> usersFromEhr = userService.getUsersFromEhr(strings);
        Set<String> collect = usersFromEhr.stream()
                .filter(x -> StrUtil.isNotBlank(x.getName()))
                .map(LdapEhrEmpDto::getName)
                .collect(Collectors.toSet());
        return String.join(",",collect);
    }

    @Transactional
    public void delete(Long id){
        logger.info("删除系统信息流水：{}", id);
        HisBusiSystemInfo hisBusiSystemInfo = hisBusiSystemInfoRepo.queryByid(id);
        if (hisBusiSystemInfo == null) {
            throw  PlatformException.errorWithOutMail("未找到流水记录");
        }
        Long id1 = hisBusiSystemInfo.getId();
        List<HisDepCostAllocation> hisDepCostAllocationList = hisDepCostAllocationRepo.queryByHisSystemInfoIdOne(hisBusiSystemInfo.getId());
        if(CollectionUtil.isNotEmpty(hisDepCostAllocationList)){
            hisDepCostAllocationRepo.deleteAll(hisDepCostAllocationList);
        }
        hisBusiSystemInfoRepo.delete(hisBusiSystemInfo);
    }

}
